package com.fdb.efp.nls.api.rest;

import com.alibaba.fastjson.JSON;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.UUIDUtil;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.efp.console.common.psd.PsdConstantSet;
import com.fdb.efp.cus.service.facade.CusWhiteListTecService;
import com.fdb.efp.cus.service.vo.CusWhiteListTecExcelVO;
import com.fdb.efp.cus.service.vo.CusWhiteListTecVO;
import com.gdrcu.efp.cus.common.ExcelException;
import com.gdrcu.efp.cus.common.util.ExcelImportUtil;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/api")
public class CusWhiteListTecController extends AbstractController  {
	
	@Autowired
	@Qualifier("cusWhiteListTecService")
	private CusWhiteListTecService cusWhiteListTecService;

	private static final String CONTENTTYPE = "application/json;charset=UTF-8";

	private static final String MODELNAME = "白名单导入模板.xls";

	private static final String SHEET1NAME = "白名单";

	private static final String IMPORT_PATH = "/template/importWhiteListInfo.xlsx";

	private List<CusWhiteListTecExcelVO> errorHisDuplicateDataList = new ArrayList<>();

	private List<CusWhiteListTecExcelVO> singleRowList = new ArrayList<>();

	/**
	 * 列表数据查询
	 * @param vo
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tecs", method=RequestMethod.POST)
	public @ResponseBody ResponseData<List<CusWhiteListTecVO>> queryCusWhiteListTecAll(@RequestBody CusWhiteListTecVO vo) {		
		List<CusWhiteListTecVO> outputVo = cusWhiteListTecService.queryAllOwner(vo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键查询详情
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tec", method=RequestMethod.GET)
	public @ResponseBody ResponseData<CusWhiteListTecVO> queryByPk() {		
		CusWhiteListTecVO inVo = new CusWhiteListTecVO();
		CusWhiteListTecVO outputVo = cusWhiteListTecService.queryByPk(inVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键删除信息
	 * @param inCusWhiteListTecVo
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tec", method=RequestMethod.DELETE)
	public @ResponseBody ResponseData<Integer> deleteByPk(@RequestBody CusWhiteListTecVO inCusWhiteListTecVo) {		
		int outputVo = cusWhiteListTecService.deleteByPk(inCusWhiteListTecVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键更新信息
	 * @param inCusWhiteListTecVo
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tec", method=RequestMethod.PUT)
	public @ResponseBody ResponseData<Integer> updateByPk(@RequestBody CusWhiteListTecVO inCusWhiteListTecVo) {	
		setUserInfoToVO(inCusWhiteListTecVo);
		List<CusWhiteListTecVO> tempVo = cusWhiteListTecService.queryByConditions(inCusWhiteListTecVo);
		if(Objects.nonNull(tempVo)) return ResponseData.create(null,ApplicationConstance.FAILURE,"证件号码是：【"+inCusWhiteListTecVo.getCertNo()+"】的客户已存在同类型白名单信息！",false);
		inCusWhiteListTecVo.setLastChgUsr(inCusWhiteListTecVo.getLoginUserId());
		inCusWhiteListTecVo.setLastChgDt(TimeUtil.getCurrentDateTime());
		int outputVo = cusWhiteListTecService.updateByPk(inCusWhiteListTecVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 新增数据
	 * @param inCusWhiteListTecVo
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tec", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Integer> insertCusWhiteListTec(@RequestBody CusWhiteListTecVO inCusWhiteListTecVo) {
		setUserInfoToVO(inCusWhiteListTecVo);
		List<CusWhiteListTecVO> tempVo = cusWhiteListTecService.queryByConditions(inCusWhiteListTecVo);
		if(Objects.nonNull(tempVo)) return ResponseData.create(null,ApplicationConstance.FAILURE,"证件号码是：【"+inCusWhiteListTecVo.getCertNo()+"】的客户已存在同类型白名单信息！",false);
		inCusWhiteListTecVo.setCusWhiteId(UUIDUtil.getUUID());
		inCusWhiteListTecVo.setCreateUser(inCusWhiteListTecVo.getLoginUserId());
		inCusWhiteListTecVo.setCreateTime(TimeUtil.getCurrentDateTime());
		int outputVo = cusWhiteListTecService.insertCusWhiteListTec(inCusWhiteListTecVo);
		return getResponseData(outputVo);
		
	}

	/**
	 * 根据主键批量删除信息
	 * @param inCusWhiteListTecVo
	 * @return
	 */
	@RequestMapping(value="/cus/white/list/tecs", method=RequestMethod.DELETE)
	public @ResponseBody ResponseData<Integer> batchDeleteByPk(@RequestBody CusWhiteListTecVO inCusWhiteListTecVo) {
		int outputVo = cusWhiteListTecService.batchDeleteByPk(inCusWhiteListTecVo);
		return getResponseData(outputVo);

	}

	/**
	 * 模板下载
	 *
	 * @author
	 * @version
	 * @since
	 */
	@RequestMapping(value = "/cus/white/list/tecs/downLoad", method = RequestMethod.GET)
	public @ResponseBody
	ResponseData<String> cusRelCherkModelDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename=" + new String((MODELNAME).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载数据导入模板开始----------------------------");
			bis = new BufferedInputStream(CusWhiteListTecController.class.getClassLoader().getResourceAsStream(IMPORT_PATH));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("模板文件下载失败：", e);
			return getResponseData(null);
		} finally {
			if (null != bis) {
				bis.close();
			}
			if (null != bos) {
				bos.close();
			}
		}
		logger.info("下载关联人数据导入模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 文件导入并解析储存到数据表
	 *
	 * @author
	 * @version
	 * @since
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value = "/cus/white/list/tecs/upload", method = RequestMethod.POST)
	public void cusWhiteListTecVOUpload(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<CusWhiteListTecVO>> result = new ResponseData<List<CusWhiteListTecVO>>();
		List<File> cusWhiteListTecVOChecks = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;

		try {
			out = respone.getOutputStream();
			//获取文件
			cusWhiteListTecVOChecks = getFileList(request);
			if (!cusWhiteListTecVOChecks.isEmpty()) {
				for (File file : cusWhiteListTecVOChecks) {
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<CusWhiteListTecExcelVO> cusWhiteListTecExcelVO = ExcelImportUtil.importExcelByClass(SHEET1NAME, file, CusWhiteListTecExcelVO.class);
					//检查导入的数据是否填写错误
//					checkExcelDatas(cusWhiteListTecExcelVO);
					//检查历史数据是否重复
					String errStr = "";
					errStr = checkHisDatas(cusWhiteListTecExcelVO);
					//组装数据
					List<CusWhiteListTecVO> inserCusWhiteListTec = new ArrayList<CusWhiteListTecVO>();
					inserCusWhiteListTec = assembleData(singleRowList);
					//执行插入操作
					int num = 0;
					if (inserCusWhiteListTec.size() > 0) num = execBatchInsertSql(inserCusWhiteListTec);
					if (num < 0) throw new Exception("插入数据出错！");
					//错误信息
					if (!StringUtil.isNullorBank(errStr)) {
						errStr = "ExcelError:" + errStr;
						throw new Exception(errStr);
					}
					//组装结果
					result = getResponseData(inserCusWhiteListTec);
				}
			} else {
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e.getMessage());
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}

	private int execBatchInsertSql(List<CusWhiteListTecVO> inserCusWhiteListTec) {
		int num = 0;
		return num = cusWhiteListTecService.batchInsertWhiteList(inserCusWhiteListTec);
	}

	private List<CusWhiteListTecVO> assembleData(List<CusWhiteListTecExcelVO> cusWhiteListTecExcelVO) throws ExcelException {
		List<CusWhiteListTecVO> list = new ArrayList<>();
		if (Objects.nonNull(cusWhiteListTecExcelVO)) {
			Iterator<CusWhiteListTecExcelVO> iterator = cusWhiteListTecExcelVO.iterator();
			while (iterator.hasNext()) {
				CusWhiteListTecExcelVO tempExcelVO = iterator.next();
				setUserInfoToVO(tempExcelVO);
				CusWhiteListTecVO tempVO = new CusWhiteListTecVO();
				tempVO.setCusWhiteId(UUIDUtil.getUUID());
				tempVO.setCertNo(tempExcelVO.getCertNo());
				tempVO.setCertType(tempExcelVO.getCertType());
				tempVO.setPrdCode(tempExcelVO.getPrdCode());
				tempVO.setPrdName(tempExcelVO.getPrdName());
				tempVO.setCusName(tempExcelVO.getCusName());
				tempVO.setMatainCategory(tempExcelVO.getMatainCategory());
				tempVO.setCreateUser(tempExcelVO.getLoginUserId());
				tempVO.setCreateTime(TimeUtil.getCurrentDateTime());
				list.add(tempVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}

	private String checkHisDatas(List<CusWhiteListTecExcelVO> cusWhiteListTecExcelVO) throws Exception {
		int errorRow = 4;
		List<Integer> errorDuplicateRowList = new ArrayList<>();
		String errorDuplicateMsg = "";
		errorHisDuplicateDataList.clear();
		Map<Integer, String> errorList = new HashMap<Integer, String>();
		Map<Integer, String> prdList = new HashMap<Integer, String>();

		for (CusWhiteListTecExcelVO item : cusWhiteListTecExcelVO) {
			boolean flag = checkDataIsUnique(item);
			if (flag) {
				errorDuplicateRowList.add(errorRow);
				prdList.put(errorRow, item.getPrdCode());
				errorHisDuplicateDataList.add(item);
			}
			errorRow += 1;
		}

		//收集没问题的导入数据
		singleRowList.clear();
		singleRowList = cusWhiteListTecExcelVO.stream().filter(a->!errorHisDuplicateDataList.contains(a)).collect(Collectors.toList());

		if (errorDuplicateRowList.size() > 0) {
			for (Integer integer : errorDuplicateRowList) {
				if (!PsdConstantSet.prdId.equals(prdList.get(integer))) {
					errorDuplicateMsg =  "第【" + integer + "】行，该客户已存在，跳过该条数据！";
				}else {
					errorDuplicateMsg =  "第【" + integer + "】行，不符合普税贷产品的身份证格式要求（18位0），跳过该条数据！";
				}
				errorList.put(integer, errorDuplicateMsg);
			}
		}

		//按key值对errorList排序并将value拼接成字符串
		String rs = "";
		rs += sortAndSpliceMap(errorList);
		return rs;
//		if (!StringUtil.isNullorBank(rs)) {
//			rs = "DataDuplicateError:" + rs;
//			throw new Exception(rs);
//		}
	}

	private String sortAndSpliceMap(Map<Integer, String> errorList) {
		String rs = "";
		//取出key值，根据key值排序
		Object[] key = errorList.keySet().toArray();
		Arrays.sort(key);
		//拼接信息
		Iterator ite = errorList.entrySet().iterator();
		while (ite.hasNext()) {
			Map.Entry string = (Map.Entry) ite.next();
			StringBuffer buffer = new StringBuffer();
			if (StringUtil.isNullorBank(rs)) {
				rs = (String) string.getValue();
			} else {
				rs = buffer.append(rs).append(",").append(string.getValue()).toString();
			}
		}
		return rs;
	}

	private boolean checkDataIsUnique(CusWhiteListTecExcelVO item) {
		if (PsdConstantSet.prdId.equals(item.getPrdCode())) {
			return !"000000000000000000".equals(item.getCertNo());
		}
		CusWhiteListTecVO cusWhiteListTecVO = new CusWhiteListTecVO();
		cusWhiteListTecVO.setCertType(item.getCertType());
		cusWhiteListTecVO.setCertNo(item.getCertNo());
		cusWhiteListTecVO.setMatainCategory(item.getMatainCategory());
		List<CusWhiteListTecVO> queryRs = cusWhiteListTecService.queryByConditions(cusWhiteListTecVO);
		return Objects.isNull(queryRs) ? false : true;
	}

	private void checkExcelDatas(List<CusWhiteListTecExcelVO> cusWhiteListTecExcelVO) {

	}


	/**
	 * 从HttpServletRequest中获取文件
	 *
	 * @author
	 * @version
	 * @since
	 */
	@SuppressWarnings("rawtypes")
	private List<File> getFileList(HttpServletRequest request) throws IOException {
		List<File> listFiles = new ArrayList<File>();
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if (multipartResolver.isMultipart(request)) {
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while (iter.hasNext()) {
				MultipartFile mFile = multiRequest.getFile(iter.next().toString());
				if (mFile != null) {
					listFiles.add(multipartToFile(mFile));
				}
			}
		}
		return listFiles;
	}

	/**
	 * 转换文件
	 *
	 * @author
	 * @version
	 * @since
	 */
	private File multipartToFile(MultipartFile multfile) throws IOException {
		CommonsMultipartFile cmf = (CommonsMultipartFile) multfile;
		DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();
		File file = dfi.getStoreLocation();
		if (file.length() < 2048) {
			File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + file.getName());
			multfile.transferTo(tmpFile);
			return tmpFile;
		}
		return file;
	}
}
